//
// Created by xunx on 2018/12/8.
//

#include "Resource.h"
#include "Shader.h"
#include "Texture2D.h"
#include "Vertices.h"
#include "Sprite.h"

#define STB_IMAGE_IMPLEMENTATION

#include "stb_image.h"

std::unordered_map<std::string, Shader> Resource::ShaderResource;
std::unordered_map<std::string, Texture2D> Resource::Texture2DResource;
std::unordered_map<std::string, Vertices> Resource::VerticesResource;
std::unordered_map<std::string, Sprite*> Resource::SpriteResource;

void Resource::LoadShader(std::string shaderName) {
    if (ShaderResource.count(shaderName))
        return;
    ShaderResource[shaderName] = LoadShaderForFile();
}

Shader Resource::LoadShaderForFile() {
    Shader shader;
    shader.Compile("Resource/NShader.vs", "Resource/NShader.fs");
    return shader;
}

Shader Resource::GetShader(std::string shaderName) {
    assert(ShaderResource.count(shaderName));
    return ShaderResource[shaderName];
}

void Resource::LoadTexture2D(const char* file, bool alpha, std::string Texture2DName) {
    if (Texture2DResource.count(Texture2DName))
        return;
    Texture2DResource[Texture2DName] = LoadTexture2DForFile(file, alpha);
}

Texture2D Resource::GetTexture2D(std::string Texture2DName) {
    assert(Texture2DResource.count(Texture2DName));
    return Texture2DResource[Texture2DName];
}

Texture2D Resource::LoadTexture2DForFile(const char* file, bool alpha) {
    Texture2D texture;
    if (alpha) {
        texture.Internal_Format = GL_RGBA;
        texture.Image_Format = GL_RGBA;
    }
    int width, height, nrChannels;
    unsigned char* image = stbi_load(file, &width, &height, &nrChannels, 0);
    if (image) {
        texture.Generate(width, height, image);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    stbi_image_free(image);
    return texture;
}

Vertices Resource::GetVertices(std::string VerticesName) {
    assert(VerticesResource.count(VerticesName));
    return VerticesResource[VerticesName];
}

void Resource::InitResource() {
    Vertices spriteVertices;
    VerticesResource["Sprite"] = spriteVertices;
    LoadShader("Sprite");
}

Sprite* Resource::CreateSprite(std::string name, float w, float h, float x, float y, float r, Texture2D texture) {
    if (SpriteResource.count(name))
        return SpriteResource[name];
    else {
        Sprite* sprite = new Sprite();
        sprite->SetTexture(texture);
        sprite->SetSize(w, h);
        sprite->SetPosition(x, y);
        sprite->SetRotate(r);
        SpriteResource[name] = sprite;
    }
}

Sprite* Resource::GetSprite(std::string name) {
    assert(SpriteResource.count(name));
    return SpriteResource[name];
}

bool Resource::DeleteSprite(std::string name) {
    if (!SpriteResource.count(name))return false;
    else{
        delete GetSprite(name);
        SpriteResource.erase(name);
    }
}

std::unordered_map<std::string, Sprite*> Resource::GetSpriteResource() {
    return SpriteResource;
}

